import { ref, onMounted, onUnmounted } from 'vue'

/**
 * 缓存数据类型定义
 */
export interface CacheData<T = any> {
  data: T
  timestamp: number
  expireTime?: number
}

/**
 * 缓存配置选项
 */
export interface CacheOptions {
  prefix?: string
  storage?: 'localStorage' | 'sessionStorage'
  enableCompression?: boolean
}

/**
 * 缓存Hook返回类型
 */
export interface CacheHook {
  getCache: <T>(key: string) => Promise<T | null>
  setCache: <T>(key: string, data: T, expireTime?: number) => Promise<void>
  removeCache: (key: string) => Promise<void>
  clearCache: (prefix?: string) => Promise<void>
  hasCache: (key: string) => Promise<boolean>
}

/**
 * 缓存Hook
 * 提供基于localStorage/sessionStorage的缓存功能
 */
export function useCache(options: CacheOptions = {}): CacheHook {
  const { prefix = 'app_cache_', storage = 'localStorage', enableCompression = false } = options

  const storageRef = ref(storage === 'localStorage' ? localStorage : sessionStorage)

  /**
   * 获取缓存键名
   */
  const getCacheKey = (key: string): string => {
    return `${prefix}${key}`
  }

  /**
   * 检查缓存是否过期
   */
  const isExpired = (cacheData: CacheData): boolean => {
    if (!cacheData.expireTime) return false
    return Date.now() > cacheData.expireTime
  }

  /**
   * 获取缓存数据
   */
  const getCache = async <T>(key: string): Promise<T | null> => {
    try {
      const cacheKey = getCacheKey(key)
      const cached = storageRef.value.getItem(cacheKey)

      if (!cached) return null

      const cacheData: CacheData<T> = JSON.parse(cached)

      // 检查是否过期
      if (isExpired(cacheData)) {
        await removeCache(key)
        return null
      }

      return cacheData.data
    } catch (error) {
      return null
    }
  }

  /**
   * 设置缓存数据
   */
  const setCache = async <T>(key: string, data: T, expireTime?: number): Promise<void> => {
    try {
      const cacheKey = getCacheKey(key)
      const cacheData: CacheData<T> = {
        data,
        timestamp: Date.now(),
        expireTime: expireTime ? Date.now() + expireTime : undefined,
      }

      storageRef.value.setItem(cacheKey, JSON.stringify(cacheData))
    } catch (error) {}
  }

  /**
   * 移除缓存数据
   */
  const removeCache = async (key: string): Promise<void> => {
    try {
      const cacheKey = getCacheKey(key)
      storageRef.value.removeItem(cacheKey)
    } catch (error) {}
  }

  /**
   * 清除缓存数据
   */
  const clearCache = async (prefixToClear?: string): Promise<void> => {
    try {
      const prefixToUse = prefixToClear || prefix
      const keysToRemove: string[] = []

      for (let i = 0; i < storageRef.value.length; i++) {
        const key = storageRef.value.key(i)
        if (key && key.startsWith(prefixToUse)) {
          keysToRemove.push(key)
        }
      }

      keysToRemove.forEach(key => storageRef.value.removeItem(key))
    } catch (error) {}
  }

  /**
   * 检查缓存是否存在
   */
  const hasCache = async (key: string): Promise<boolean> => {
    try {
      const cacheKey = getCacheKey(key)
      const cached = storageRef.value.getItem(cacheKey)

      if (!cached) return false

      const cacheData: CacheData = JSON.parse(cached)

      // 检查是否过期
      if (isExpired(cacheData)) {
        await removeCache(key)
        return false
      }

      return true
    } catch (error) {
      return false
    }
  }

  // 监听存储变化事件
  if (typeof window !== 'undefined') {
    onMounted(() => {
      const handleStorageChange = (event: StorageEvent) => {
        if (event.storageArea === storageRef.value) {
          // 可以在这里添加存储变化的处理逻辑
        }
      }

      window.addEventListener('storage', handleStorageChange)

      onUnmounted(() => {
        window.removeEventListener('storage', handleStorageChange)
      })
    })
  }

  return {
    getCache,
    setCache,
    removeCache,
    clearCache,
    hasCache,
  }
}

/**
 * 内存缓存Hook
 * 提供基于内存的临时缓存功能
 */
export function useMemoryCache<T = any>() {
  const cache = new Map<string, { data: T; expireTime?: number }>()

  const set = (key: string, data: T, ttl?: number): void => {
    const expireTime = ttl ? Date.now() + ttl : undefined
    cache.set(key, { data, expireTime })
  }

  const get = (key: string): T | null => {
    const item = cache.get(key)
    if (!item) return null

    if (item.expireTime && Date.now() > item.expireTime) {
      cache.delete(key)
      return null
    }

    return item.data
  }

  const remove = (key: string): void => {
    cache.delete(key)
  }

  const clear = (): void => {
    cache.clear()
  }

  return {
    set,
    get,
    remove,
    clear,
  }
}

export default useCache
